﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.TemplateWizard;
using System.IO;
using EnvDTE;
using System.Windows.Forms;

namespace DNNTestDrivenModuleTemplateWizard
{
    public class RootWizardImpl : IWizard
    {
        private string safeprojectname;
        public const string SafeProjectNameKey = "$safeprojectname$";
        private static Dictionary<string, string> globalParameters = new Dictionary<string, string>();
        private static Dictionary<string, string> s_SolutionFiles = new Dictionary<string, string>
        {
            {"CodeAnalysisRule\\Nova Minimum Mandatory Rules.ruleset", "DNNTestDrivenModuleTemplateWizard.Resources.CodeAnalysisRule.Nova Minimum Mandatory Rules.ruleset"},
            {"Libs\\DotNetNuke.Tests.UI.WatiN.Common.dll", "DNNTestDrivenModuleTemplateWizard.Resources.Libs.DotNetNuke.Tests.UI.WatiN.Common.dll"},
            {"Libs\\DotNetNuke.Tests.UI.WatiN.Utilities.dll", "DNNTestDrivenModuleTemplateWizard.Resources.Libs.DotNetNuke.Tests.UI.WatiN.Utilities.dll"},
            {"Libs\\Gallio.dll", "DNNTestDrivenModuleTemplateWizard.Resources.Libs.Gallio.dll"},
            {"Libs\\Interop.SHDocVw.dll", "DNNTestDrivenModuleTemplateWizard.Resources.Libs.Interop.SHDocVw.dll"},
            {"Libs\\MbUnit.dll", "DNNTestDrivenModuleTemplateWizard.Resources.Libs.MbUnit.dll"},
            {"Libs\\Microsoft.SqlServer.ConnectionInfo.dll", "DNNTestDrivenModuleTemplateWizard.Resources.Libs.Microsoft.SqlServer.ConnectionInfo.dll"},
            {"Libs\\Microsoft.SqlServer.Management.Sdk.Sfc.dll", "DNNTestDrivenModuleTemplateWizard.Resources.Libs.Microsoft.SqlServer.Management.Sdk.Sfc.dll"},
            {"Libs\\Microsoft.SqlServer.Smo.dll", "DNNTestDrivenModuleTemplateWizard.Resources.Libs.Microsoft.SqlServer.Smo.dll"},
            {"Libs\\Microsoft.SqlServer.SqlEnum.dll", "DNNTestDrivenModuleTemplateWizard.Resources.Libs.Microsoft.SqlServer.SqlEnum.dll"},
            {"Libs\\Moq.dll", "DNNTestDrivenModuleTemplateWizard.Resources.Libs.Moq.dll"},
            {"Libs\\WatiN.Core.dll", "DNNTestDrivenModuleTemplateWizard.Resources.Libs.WatiN.Core.dll"},
            {"Libs\\WebFormsMvp.dll", "DNNTestDrivenModuleTemplateWizard.Resources.Libs.WebFormsMvp.dll"},
        };
        private StringBuilder m_MessageBuilder = new StringBuilder();
        private EnvDTE80.DTE2 m_DTEObject;

        public static string SafeProjectName
        {
            get
            {
                var safeProjectName = globalParameters[SafeProjectNameKey];
                return safeProjectName;
            }
        }

        public static IEnumerable<KeyValuePair<string, string>> GlobalParameters
        {
            get { return globalParameters; }
        }

        private void CreateSolutionFiles(string soutionFullname)
        {
            var resFolder = Path.Combine(soutionFullname, "Resources");
            var libFolder = Path.Combine(resFolder, "Libs");
            var codRuleFolder = Path.Combine(resFolder, "CodeAnalysisRule");
            Log("Create Folder: " + resFolder);
            Directory.CreateDirectory(resFolder);
            Log("Create Folder: " + libFolder);
            Directory.CreateDirectory(libFolder);
            Log("Create Folder: " + codRuleFolder);
            Directory.CreateDirectory(codRuleFolder);

            var assembly = typeof(RootWizardImpl).Assembly;
            foreach (var keyPair in s_SolutionFiles)
            {
                string filename = Path.Combine(resFolder, keyPair.Key);
                using (Stream stream = assembly.GetManifestResourceStream(keyPair.Value))
                {
                    using (BinaryReader reader = new BinaryReader(stream))
                    {
                        byte[] data = reader.ReadBytes((int)stream.Length);
                        Log("Create File: " + filename);
                        File.WriteAllBytes(filename, data);
                    }
                }
            }
        }

        private void Log(string message)
        {
            m_MessageBuilder.AppendLine(message);
        }

        private static string GetSolutionPath(EnvDTE80.Solution2 solution)
        {
            var firstProject = FirstProject(solution);
            var projectPath = firstProject.Properties.Item("FullPath").Value.ToString();
            DirectoryInfo dir = new DirectoryInfo(projectPath);
            return dir.Parent.FullName;
        }

        private static Project FirstProject(EnvDTE80.Solution2 solution)
        {
            Project project = solution.Projects
                .Cast<Project>()
                .FirstOrDefault(d => HasProperty(d.Properties, "FullPath"));
            return project;
        }

        private static bool HasProperty(Properties properties, string propertyName)
        {
            if (properties != null)
            {
                return properties.Cast<Property>().Any(item => item != null && item.Name == propertyName);
            }
            return false;
        }
        #region IWizard Members

        public void BeforeOpeningFile(EnvDTE.ProjectItem projectItem) { }

        public void ProjectFinishedGenerating(EnvDTE.Project project) { }

        public void ProjectItemFinishedGenerating(EnvDTE.ProjectItem projectItem) { }

        public void RunFinished()
        {
            try
            {
                EnvDTE80.Solution2 solution = (EnvDTE80.Solution2)m_DTEObject.Solution;
                var solutionFolder = GetSolutionPath(solution);
                Log("Solution FullPath: " + solutionFolder);
                CreateSolutionFiles(solutionFolder);

                Project resFolderProject = solution.AddSolutionFolder("Resources");
                EnvDTE80.SolutionFolder resSolutionFolder = (EnvDTE80.SolutionFolder)resFolderProject.Object;
                Project libFolderProject = resSolutionFolder.AddSolutionFolder("Libs");
                Project codeRuleProject = resSolutionFolder.AddSolutionFolder("CodeAnalysisRule");
                var files = Directory.GetFiles(Path.Combine(solutionFolder, "Resources\\Libs"));
                foreach (var file in files)
                {
                    Log("Add Project Item To Libs Solution Folder: " + file);
                    libFolderProject.ProjectItems.AddFromFile(file);
                }
                files = Directory.GetFiles(Path.Combine(solutionFolder, "Resources\\CodeAnalysisRule"));
                foreach (var file in files)
                {
                    Log("Add Project Item To CodeAnalysisRule Solution Folder: " + file);
                    codeRuleProject.ProjectItems.AddFromFile(file);
                }
            }
            catch (Exception exp)
            {
                Log(exp.ToString());
                MessageBox.Show("RunFinished occur error: " + this.m_MessageBuilder);
            }
        }

        public void RunStarted(object automationObject,
            Dictionary<string, string> replacementsDictionary,
            WizardRunKind runKind, object[] customParams)
        {
            safeprojectname = replacementsDictionary[SafeProjectNameKey];
            globalParameters[SafeProjectNameKey] = safeprojectname;
            m_DTEObject = (automationObject as EnvDTE80.DTE2);
        }

        public bool ShouldAddProjectItem(string filePath) { return true; }

        #endregion
    }
}
